﻿#if UNITY_EDITOR
using System.Collections.Generic;
using System.Xml.Serialization;
using Unity.Collections;
/// <summary>
/// xlsx表脚本生成设定
/// </summary>
[XmlRoot("ESF_Xml_XlsxTable_ScriptBuildSetting")]
public class ESF_Xml_XlsxTable_ScriptBuildSetting : AbsESF_Xml
{
    /// <summary>
    /// 表索引
    /// </summary>
    [XmlElement("表索引")]
    [ReadOnly()]
    public int tableIndex;

    /// <summary>
    /// 表名称
    /// </summary>
    [XmlElement("表名称")]
    [ReadOnly()]
    public string tableName;

    /// <summary>
    /// 脚本类名
    /// </summary>
    [XmlElement("脚本类名")]
    [ReadOnly()]
    public string className;    

    /// <summary>
    /// 脚本帮助类Select类名
    /// </summary>
    [XmlElement("脚本帮助类Select类名")]
    [ReadOnly()]
    [ESF_GUIBrower()]
    public string helperSelectFileName;

    /// <summary>
    /// 脚本扩展类类名
    /// </summary>
    [XmlElement("脚本扩展类类名")]
    [ReadOnly()]
    [ESF_GUIBrower()]
    public string extendFileName;

    /// <summary>
    /// Select方法名
    /// </summary>
    [XmlElement("Select方法名")]
    [ReadOnly()]
    public string selMetN;

    /// <summary>
    /// 是否有主键
    /// </summary>
    [XmlElement("是否有主键")]
    [ReadOnly()]
    public bool hasPK;

    /// <summary>
    /// 主键数量
    /// </summary>
    [XmlElement("主键数量")]
    [ReadOnly()]
    public int pkCount;

    /// <summary>
    /// 验证Key代码
    /// </summary>
    [XmlElement("验证Key代码")]
    [ReadOnly()]
    public string verifyKeyCode;

    /// <summary>
    /// 主键Key值代码
    /// </summary>
    [XmlElement("主键Key值代码")]
    [ReadOnly()]
    public string pkKeyCode;

    /// <summary>
    /// 数据Key类型
    /// </summary>
    [XmlElement("数据Key类型")]
    [ReadOnly()]
    public string dbKeyType;

    /// <summary>
    /// Db库值类型组
    /// </summary>
    [XmlElement("Db库值类型组")]
    [ReadOnly()]
    public ESF_Xml_XlsxTable_DbValueType_ScriptBuildSetting[] dbTypes;

    /// <summary>
    /// 列组
    /// </summary>
    [XmlElement("列组")]
    [ReadOnly()]
    public ESF_Xml_XlsxTableColumn_ScriptBuildSetting[] columns;

    /// <summary>
    /// 删除判定列组
    /// </summary>
    [XmlElement("删除判定列组")]
    [ReadOnly()]
    public ESF_Xml_XlsxTableColumn_ScriptBuildSetting[] deleteColumns;

    /// <summary>
    /// 主键列组
    /// </summary>
    [XmlElement("主键列组")]
    [ReadOnly()]
    public ESF_Xml_XlsxTableColumn_ScriptBuildSetting[] pkColumns;

    /// <summary>
    /// OnResolve
    /// </summary>
    protected override void OnResolve()
    {
        base.OnResolve();
        hasPK = false;
        dbKeyType = string.Empty;
        pkCount = 0;
        List<string> sizeOfBitCode = new List<string>();
        List<string> sizeOfTip = new List<string>();
        List<string> sizeOfCond = new List<string>();
        ESF_CSharpCodeAttribute ulongAttr = ESF_enCS2UnityDataType.ULong.ESF_FirstAttribute<ESF_CSharpCodeAttribute>();
        ESF_CSharpCodeAttribute intAttr = ESF_enCS2UnityDataType.Int.ESF_FirstAttribute<ESF_CSharpCodeAttribute>();
        string helperFix = $"{ESF_Logic.xlsxAutoBuildFolder.xml.xlsxScriptHelperClassName}.";
        string sizeFix = "_sizeOf";
        List<ESF_Xml_XlsxTableColumn_ScriptBuildSetting> pkCols = new List<ESF_Xml_XlsxTableColumn_ScriptBuildSetting>();
        List<ESF_Xml_XlsxTableColumn_ScriptBuildSetting> delCols = new List<ESF_Xml_XlsxTableColumn_ScriptBuildSetting>();        
        if (columns != null)
        {
            foreach (var key in columns)
            {
                hasPK |= key.isPK;
                if (key.isPK)
                {
                    pkCount++;
                    dbKeyType = key.sizeofType;
                    sizeOfCond.Add($"{helperFix}{key.dbType}{sizeFix}");
                    sizeOfTip.Add($"{key.csName}_sizeof({{{helperFix}{key.dbType}{sizeFix}}})");
                    pkCols.Add(key);
                }
                if (key.isDelete)
                {
                    delCols.Add(key);
                }
            }
        }
        deleteColumns = delCols.ToArray();
        pkColumns = pkCols.ToArray();

        if (pkCount != 1)
        {
            dbKeyType = ulongAttr.unityType;
        }
        List<string> codes = new List<string>();

        #region 生成 verifyKeyCode
        if (sizeOfCond.Count > 0)
        {
            codes.Add("bool result = false;");
            codes.Add($"int max = {helperFix}{ulongAttr.unityType}{sizeFix};");
            codes.Add($"int cur = {sizeOfCond.ESF_Join(enESF_SeparatorSymbol.Plus)};");
            codes.Add("result = max >= cur;");
            codes.Add("if (!result)");
            codes.Add("{");
            codes.Add($"{ESF_Logic.xlsxAutoBuildFolder.xml.logErrorMethod}($\"{sizeOfTip.ESF_Join(enESF_SeparatorSymbol.Plus)} > {{max}}\");");
            codes.Add("}");
            codes.Add("return result;");
        }
        else
        {
            codes.Add("return true");
        }
        verifyKeyCode = codes.ESF_Join(enESF_SeparatorSymbol.NewLine);
        #endregion

        codes.Clear();

        #region 生成pkKeyCode
        if (pkCols != null && pkCols.Count > 0)
        {
            string sizeofType = intAttr.unityType;
            List<string> sizeofFix = new List<string>();
            string getHashCode = ".GetHashCode()";            
            if (pkCols.Count > 1)
            {
                for (int i = 0; i < pkCols.Count; i++)
                {                     
                    switch (i)
                    {
                        case 0:
                            if (pkCols[i].isHashCode)
                            {
                                sizeOfBitCode.Add($"({dbKeyType}){pkCols[i].csFormalName}{getHashCode}");
                            }
                            else if (pkCols[i].isBool)
                            {
                                sizeOfBitCode.Add($"({dbKeyType})({pkCols[i].csFormalName}?1:0)");
                            }
                            else if (pkCols[i].unityType.Equals(ulongAttr.unityType))
                            {
                                sizeOfBitCode.Add($"{pkCols[i].csFormalName}");
                            }
                            else
                            {
                                sizeOfBitCode.Add($"({dbKeyType}){pkCols[i].csFormalName}");
                            }
                            sizeofFix.Add($"{helperFix}{pkCols[i].dbType}{sizeFix}");
                            break;
                        case 1:
                            if (pkCols[i].isHashCode)
                            {
                                sizeOfBitCode.Add($"(({dbKeyType}){pkCols[i].csFormalName}{getHashCode} << {sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)})");
                            }
                            else if (pkCols[i].isBool)
                            {
                                sizeOfBitCode.Add($"(({dbKeyType})({pkCols[i].csFormalName}?1:0) << {sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)})");
                            }
                            else if (pkCols[i].unityType.Equals(ulongAttr.unityType))
                            {
                                sizeOfBitCode.Add($"({pkCols[i].csFormalName} << {sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)})");
                            }
                            else
                            {
                                sizeOfBitCode.Add($"(({dbKeyType}){pkCols[i].csFormalName} << {sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)})");
                            }
                            sizeofFix.Add($"{helperFix}{pkCols[i].dbType}{sizeFix}");
                            break;
                        default:
                            if (pkCols[i].isHashCode)
                            {
                                sizeOfBitCode.Add($"(({dbKeyType}){pkCols[i].csFormalName}{getHashCode} << ({sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)}))");
                            }
                            else if (pkCols[i].isBool)
                            {
                                sizeOfBitCode.Add($"(({dbKeyType})({pkCols[i].csFormalName}?1:0) << ({sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)}))");
                            }
                            else if (pkCols[i].unityType.Equals(ulongAttr.unityType))
                            {
                                sizeOfBitCode.Add($"({pkCols[i].csFormalName} << ({sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)}))");
                            }
                            else
                            {
                                sizeOfBitCode.Add($"(({dbKeyType}){pkCols[i].csFormalName} << ({sizeofFix.ESF_Join(enESF_SeparatorSymbol.Plus)}))");
                            }
                            sizeofFix.Add($"{helperFix}{pkCols[i].dbType}{sizeFix}");
                            break;
                    }
                }                
                codes.Add($"return {sizeOfBitCode.ESF_Join(enESF_SeparatorSymbol.Plus)};");                
            }
            else
            {
                if (pkCols[0].isHashCode)
                {
                    if (dbKeyType.Equals(intAttr.unityType))
                    {
                        codes.Add($"return {pkCols[0].csFormalName}{getHashCode};");
                    }
                    else
                    {
                        codes.Add($"return ({dbKeyType}){pkCols[0].csFormalName}{getHashCode};");
                    }                    
                }
                else if (pkCols[0].isBool)
                {
                    codes.Add($"return ({dbKeyType})({pkCols[0].csFormalName}?1:0);");
                }
                else if (pkCols[0].unityType.Equals(dbKeyType))
                {
                    codes.Add($"return {pkCols[0].csFormalName};");
                }
                else
                {
                    codes.Add($"return ({dbKeyType}){pkCols[0].csFormalName};");
                }
            }
        }
        pkKeyCode = codes.ESF_Join(enESF_SeparatorSymbol.NewLine);
        #endregion
    }
}

/// <summary>
/// xlsx表Db库值类型生成设定
/// </summary>
[XmlRoot("ESF_Xml_XlsxTable_DbValueType_ScriptBuildSetting")]
public class ESF_Xml_XlsxTable_DbValueType_ScriptBuildSetting : AbsESF_Xml
{
    /// <summary>
    /// db类型
    /// </summary>
    [XmlElement("db类型")]
    [ReadOnly()]
    public string dbType;

    /// <summary>
    /// unity类型
    /// </summary>
    [XmlElement("unity类型")]
    [ReadOnly()]
    public string unityType;

    /// <summary>
    /// cs类型
    /// </summary>
    [XmlElement("cs类型")]
    [ReadOnly()]
    public ESF_enCS2UnityDataType csType;

    /// <summary>
    /// db类型数量
    /// </summary>
    [XmlElement("db类型数量")]
    [ReadOnly()]
    public int dbTypeCount;
}

/// <summary>
/// xlsx表列脚本生成设定
/// </summary>
[XmlRoot("ESF_Xml_XlsxTableColumn_ScriptBuildSetting")]
public class ESF_Xml_XlsxTableColumn_ScriptBuildSetting : AbsESF_Xml
{
    /// <summary>
    /// CS名称
    /// </summary>
    [XmlElement("CS名称")]
    [ReadOnly()]
    public string csName;

    /// <summary>
    /// CS形参名称
    /// </summary>
    [XmlElement("CS形参名称")]
    [ReadOnly()]
    public string csFormalName;

    /// <summary>
    /// CS类型名称
    /// </summary>
    [XmlElement("CS类型")]
    [ReadOnly()]
    public ESF_enCS2UnityDataType csType;

    /// <summary>
    /// unity类型
    /// </summary>
    [XmlElement("unity类型")]
    [ReadOnly()]
    public string unityType;

    /// <summary>
    /// sizeof类型
    /// </summary>
    [XmlElement("sizeof类型")]
    [ReadOnly()]
    public string sizeofType;

    /// <summary>
    /// db数据库类型
    /// </summary>
    [XmlElement("db数据库类型")]
    [ReadOnly()]
    public string dbType;

    /// <summary>
    /// db数据库序号
    /// </summary>
    [XmlElement("db数据库序号")]
    [ReadOnly()]
    public int dbOrdinal;

    /// <summary>
    /// 字段描述
    /// </summary>
    [XmlElement("字段描述")]
    [ReadOnly()]
    public string fieldSummary;

    /// <summary>
    /// 字段形参描述
    /// </summary>
    [XmlElement("形参描述")]
    [ReadOnly()]
    public string formalSummary;

    /// <summary>
    /// 是否主键
    /// </summary>
    [XmlElement("是否主键")]
    [ReadOnly()]
    public bool isPK;

    /// <summary>
    /// 是否是删除判定
    /// </summary>
    [XmlElement("是否是删除判定")]
    [ReadOnly()]
    public bool isDelete;

    /// <summary>
    /// 是否可修改
    /// </summary>
    [XmlElement("是否可修改")]
    [ReadOnly()]
    public bool canModify;

    /// <summary>
    /// 是否是HashCode类型
    /// </summary>
    [XmlElement("是否是HashCode类型")]
    [ReadOnly()]
    public bool isHashCode;

    /// <summary>
    /// 是否是Bool类型
    /// </summary>
    [XmlElement("是否是Bool类型")]
    [ReadOnly()]
    public bool isBool;

    /// <summary>
    /// xlsx表列序号
    /// </summary>
    [XmlElement("xlsx表列序号")]
    [ReadOnly()]
    public int xlsxOrdinal;

    /// <summary>
    /// xlsx表行索引
    /// </summary>
    [XmlElement("xlsx表行索引")]
    [ReadOnly()]
    public int xlsxRowIndex;
}
#endif
